package educrypt.ciphers;

import educrypt.commons.*;
import educrypt.i18n.Messages;
import educrypt.log.ObservableLogger;
import educrypt.log.SimpleLogger;

public class Caesar {

	private Alphabet alphabet, key;

	public Caesar(Alphabet alphabet, int offset) {
		this.alphabet = alphabet;
		generateKey(offset);

		logCipherDetails(offset);
	}

	private void logCipherDetails(int offset) {
		// Log to console
		SimpleLogger logger = ObservableLogger.getInstance();
		logger.log(SimpleLogger.TITLE,
				"---- " + Messages.getString("cipherCaesar") + " ----");

		logger.log(SimpleLogger.TITLE, Messages.getString("guiAlphabet"));
		logger.log(SimpleLogger.CONTENT, alphabet.getSymbols());

		logger.log(SimpleLogger.TITLE, Messages.getString("guiKeyword"));
		logger.log(SimpleLogger.CONTENT, Integer.toString(offset));

		logger.log(SimpleLogger.TITLE, Messages.getString("guiGeneratedKey"));
		logger.log(SimpleLogger.CONTENT, key.getSymbols());
		logger.log("");
	}

	private void generateKey(int offset) {
		this.key = this.alphabet.rotate(-offset);
	}

	public Text encode(Text plainText) {
		StringBuffer cipherText = new StringBuffer(plainText.size());
		for (char symbol : plainText) {
			cipherText.append(encodeSymbol(symbol));
		}
		return new Text(cipherText.toString());
	}

	private char encodeSymbol(char symbol) {
		char cipherSymbol;
		boolean isUpperCase = Character.isUpperCase(symbol);
		if (isUpperCase) {
			symbol = Character.toLowerCase(symbol);
		}
		int pos = alphabet.getSymbolPosition(symbol);
		if (pos > -1) {
			cipherSymbol = key.getSymbolAt(pos);
		} else { // If the symbol doesn't belong to the alphabet it will not
					// be encoded
			cipherSymbol = symbol;
		}
		if (isUpperCase) {
			cipherSymbol = Character.toUpperCase(cipherSymbol);
		}
		return cipherSymbol;
	}

	public Text decode(Text cipherText) {
		StringBuffer plainText = new StringBuffer(cipherText.size());
		for (char symbol : cipherText) {
			plainText.append(decodeSymbol(symbol));
		}
		return new Text(plainText.toString());
	}

	private char decodeSymbol(char symbol) {
		char plainSymbol;
		boolean isUpperCase = Character.isUpperCase(symbol);

		int pos = key.getSymbolPosition(symbol);
		if (alphabet.containsSymbol(symbol)) {
			plainSymbol = alphabet.getSymbolAt(pos);
		} else { // If the symbol doesn't belong to the alphabet it will not
					// be decoded
			plainSymbol = symbol;
		}
		if (isUpperCase) {
			plainSymbol = Character.toUpperCase(plainSymbol);
		}
		return plainSymbol;
	}
}
